let Mongodb = require('../../database/mongodb');
let exceljs = require('../../utils/exceljs')

class ExportService {
  constructor () {
    this.dataCache = []
    this.header = []
    this.complexHeader = []
    this.enumTypes = []
    this.tableConfigs = []
    this.xtcsEx = []
  }

  getExcel (tableName, condition) {
    this.initParam()
    let workbook = exceljs.createWorkBook()
    let worksheet = workbook.getWorksheet(1)
    if (this.complexHeader.length > 0) {
      exceljs.setComplexHeader(worksheet, this.complexHeader, this.header)
      exceljs.setHeaderRowStyle(worksheet, 1)
      exceljs.setHeaderRowStyle(worksheet, 2)
    } else {
      worksheet.columns = this.header
      exceljs.setHeaderRowStyle(worksheet)
    }
    return new Promise((resolve, reject) => {
      initFormateData.call(this).then(() => {
        return getData(tableName, condition)
      }).then((data) => {
        return this.formateData.call(this, data)
      }).then((data) => {
        worksheet.addRows(data)
        if (this.complexHeader.length > 0) {
          exceljs.setDataRowStyle(worksheet, data, 3)
        } else {
          exceljs.setDataRowStyle(worksheet, data)
        }
        resolve(workbook)
      }).catch((err) => {
        reject(err)
      })
    })
  }

  // 格式化数据
  getPropertyValue (key, id, idName = 'id', valueName = 'name') {
    if (id && this.dataCache[key] && this.dataCache[key].length > 0) {
      let data
      for (let index = 0; index < this.dataCache[key].length; index++) {
        const item = this.dataCache[key][index];
        if (item[idName] == id) {
          data = item
        }
      }
      if (data && data[valueName]) {
        if (data['version']) {
          return data[valueName] + '(' + data['version'] + ')'
        } else {
          return data[valueName]
        }
      } else {
        return ''
      }
    } else {
      return ''
    }
  }
  
  // 格式化数据
  dataFormater (key, id, idName = 'id', valueName = 'name') {
    if (id && this.dataCache[key] && this.dataCache[key].length > 0) {
      let data
      for (let index = 0; index < this.dataCache[key].length; index++) {
        const item = this.dataCache[key][index];
        if (item[idName] == id) {
          data = item
        }
      }
      if (data && data[valueName]) {
        if (data['version']) {
          return data[valueName] + '(' + data['version'] + ')'
        } else {
          return data[valueName]
        }
      } else {
        return ''
      }
    } else {
      return ''
    }
  }

  // 格式化列表数据
  dataArrFormater (key, idArr, idName = 'id', valueName = 'name') {
    if (idArr && this.dataCache[key] && this.dataCache[key].length > 0) {
      let datas = []
      for (let index = 0; index < this.dataCache[key].length; index++) {
        const item = this.dataCache[key][index];
        if (idArr.indexOf(item[idName]) != -1) {
          datas.push(item)
        }
      }
      var names = ''
      for (var i = 0; i < datas.length; i++) {
        if (i !== datas.length - 1) {
          names += (datas[i][valueName] + ',')
        } else {
          names += datas[i][valueName]
        }
      }
      return names
    } else {
      return ''
    }
  }

  /**
   * 格式化金额显示
   * @param {*金额} s
   * @param {*保留位数} n
   */
  numberFormater (s, n) {
    if (s === undefined) return ''
    n = n > 0 && n <= 20 ? n : 2
    s = parseFloat((s + '').replace(/[^\d\\.-]/g, '')).toFixed(n) + ''
    let l = s.split('.')[0].split('').reverse()
    let r = s.split('.')[1]
    let t = ''
    for (let i = 0; i < l.length; i++) {
      t += l[i] + ((i + 1) % 3 === 0 && (i + 1) !== l.length ? ',' : '')
    }
    return t.split('').reverse().join('') + '.' + r
  }

  /**
   * boolean值转换
   * @param {*} b 
   */
  booleanFormatter (b, c = '是'){
    if (b) {
      return c
    }
  }


  // 格式化日期
  dateFormater (dateNum, fmt) {
    if (!dateNum) {
      return ''
    }
    var date = new Date(dateNum)
    var o = {
      'M+': date.getMonth() + 1,
      'd+': date.getDate(),
      'h+': date.getHours(),
      'm+': date.getMinutes(),
      's+': date.getSeconds(),
      'q+': Math.floor((date.getMonth() + 3) / 3),
      'S': date.getMilliseconds()
    }
    if (/(y+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
    }
    for (var k in o) {
      if (new RegExp('(' + k + ')').test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
      }
    }
    return fmt
  }
  
  // 初始化格式化需要数据
  initParam () {}

  // 子类覆盖该方法
  formateData (dataList) {}
}

function processCondtion (condition) {
  let result = {}
  for (let name in condition) {
    if (name === 'like') {
      for (let c in condition[name]) {
        if (condition.like[c]) {
          result[c] = new RegExp(condition.like[c], 'i')
        }
      }
    } else if (Array.isArray(condition[name])) {
      result[name] = []
      for (let index = 0; index < condition[name].length; index++) {
        const element = condition[name][index]
        result[name].push(processCondtion(element))
      }
    } else {
      result[name] = condition[name]
    }
  }
  return result
}

// 私有方法
function getData (tableName, queryParam) {
  return new Promise((resolve, reject) => {
    let conditions = {}
    if (queryParam.condition) {
      conditions = processCondtion(queryParam.condition)
    } else {
      conditions = processCondtion(queryParam)
    }
    Mongodb.find(tableName, conditions, queryParam.fields || null, queryParam.sort, (err, docs) => {
      if (err) {
        reject(err);
      } else {
        resolve(docs);
      }
    });
  });
}

function getTableData (config) {
  return new Promise((resolve, reject) => {
    Mongodb.find(config.tableName, config.condition || {}, {}, {}, (err, docs) => {
      if (err) {
        reject(err);
      } else {
        this.dataCache[config.tableName] = docs
        resolve();
      }
    });
  });
}

function getXtcsExData (csName) {
  return new Promise((resolve, reject) => {
    Mongodb.find('params', {csName: csName}, {}, {}, (err, docs) => {
      if(err) {
        reject(err);
      } else {
        this.dataCache[csName] = docs[0].exValue
        resolve();
      }
    });
  });
}

function getEnum (enumTypeKey) {
  return new Promise((resolve, reject) => {
    Mongodb.find('param_exts', {csName: enumTypeKey}, {}, {}, (err, docs) => {
      if (err) {
        reject(err);
      } else {
        this.dataCache[enumTypeKey] = docs
        resolve();
      }
    });
  });
}

function initFormateData () {
  return new Promise((resolve, reject) => {
    const enumPromise = this.enumTypes.map((key) => {
      return getEnum.call(this, key);
    });
    const baseInfoPromise = this.tableConfigs.map((config) => {
      return getTableData.call(this, config)
    })
    const xtcsExPromise = this.xtcsEx.map((csName) => {
      return getXtcsExData.call(this, csName)
    })
    Promise.all(enumPromise.concat(baseInfoPromise, xtcsExPromise)).then((data) => {
      resolve()
    }).catch((err) => {
      reject(err)
    })
  })
}

module.exports = ExportService